﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using QT.Windows.Shell;

namespace IISLogAnalytics
{
    public partial class Analy : GlassForm
    {
        #region Attributes

        private string mySQL = "SELECT logfilename,s-sitename as sitename,TO_STRING(TO_LOCALTIME(TO_TIMESTAMP([date], [time])),'yyyy-MM-dd') as ldate,c-ip as clientip, cs-uri-stem as url,count(*) as Recordcount,'' as iparea,'' as ipaddress,'' as comment,'' as stype INTO Analy_temp FROM {0} WHERE TO_LOWERCASE (EXTRACT_EXTENSION(cs-uri-stem)) {1} IN ('{2}') group by logfilename,sitename,ldate,clientip,url";

        private string QQWryPath = Application.StartupPath + @"\QQWry.Dat";
        private bool UpdateIPAddress = false;
        private int UpdateIPNumber = 0;

        private Thread myThread = null;
        private delegate List<string> myDeleGategetListBox();
        private delegate void myDeleGateAddItem(string filePath);
        private delegate void myDeleGatesetMsg(int index,string s);
        private delegate void myDeleGateoutMsgInRichTextBox(string s);
        private delegate void myDeleGatesetButton(bool b);
        private string DirPath = "";
        private string LogPath = Environment.CurrentDirectory+@"\logs";

        #endregion

        #region Analy

        public Analy()
        {
            InitializeComponent();
            this.panel1.BringToFront();
        }

        private void Analy_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            if (myThread != null && myThread.IsAlive)
            {
                if (MessageBox.Show("正在进行日志分析，确认要强制退出吗？", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.Cancel)
                {
                    return;
                }

                myThread.Abort();
            }
            e.Cancel = false;
        }

        #endregion

        #region Event

        #region GlassButton

        private void gbtnAddFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog myOpenFileDialog = new OpenFileDialog();
            myOpenFileDialog.Filter = "IISW3C日志文件 (*.log)|*.log|AllFiles (*.*)|*.*";
            myOpenFileDialog.Multiselect = true;
            myOpenFileDialog.AutoUpgradeEnabled = true;

            if (myOpenFileDialog.ShowDialog() == DialogResult.Cancel) return;
            string[] logFiles = myOpenFileDialog.FileNames;
            myOpenFileDialog.Dispose();

            foreach (string file in logFiles) this.lbFiles.Items.Add(file);
        }

        private void gbtnAddDirctory_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog myFolderBrowserDialog = new FolderBrowserDialog();
            if (myFolderBrowserDialog.ShowDialog() == DialogResult.Cancel) return;
            DirPath = myFolderBrowserDialog.SelectedPath;
            myFolderBrowserDialog.Dispose();
            myThread = new Thread(new ThreadStart(ThreadSearch));
            myThread.Start();
        }

        private void gbtnDelete_Click(object sender, EventArgs e)
        {
            if (this.lbFiles.SelectedItems != null)
            {
                while (this.lbFiles.SelectedItems.Count > 0)
                {
                    this.lbFiles.Items.Remove(this.lbFiles.SelectedItems[0]);
                }
            }
        }

        private void gbtnNext_Click(object sender, EventArgs e)
        {
            if (this.lbFiles.Items.Count == 0)
            {
                MessageBox.Show("请添加日志文件");
                return;
            }

            string filtertype = ConfigurationManager.AppSettings["filtertype"];
            if (filtertype == "0") this.rbtnInclude.Checked = true;
            else this.rbtnExclude.Checked = true;
            string filters = ConfigurationManager.AppSettings["filter"];
            this.tbFilter.Text = filters;
            this.tbPath.Text = QQWryPath;
            this.panel2.BringToFront();
        }

        private void gbtnPrevious_Click(object sender, EventArgs e)
        {
            this.panel1.BringToFront();
        }

        private void gbtnAnaly_Click(object sender,EventArgs e)
        {
            Configuration appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            appConfig.AppSettings.Settings["filtertype"].Value = this.rbtnInclude.Checked ? "0" : "1";
            appConfig.AppSettings.Settings["filter"].Value = this.tbFilter.Text;
            appConfig.Save();

            this.progressBar1.Maximum = this.lbFiles.Items.Count * 9 + 3;
            this.progressBar1.Value = 0;
            this.lblMsg.Text = "";
            this.gbtnOk.Enabled = false;
            this.rtbProgress.Text = "";
            this.rtbProgress.Visible = false;
            this.btnDetail.Visible = true;

            if (this.rbtnAllIP.Checked) UpdateIPNumber = 0;
            if (this.rbtnMultiIP.Checked) UpdateIPNumber = (int)this.nudIP.Value;
            if (this.rbtnNoIP.Checked) UpdateIPAddress = false;
            else UpdateIPAddress = true;

            this.panel3.BringToFront();
            myThread = new Thread(new ThreadStart(ThreadAnaly));
            myThread.Start();
        }

        private void btnDetail_Click(object sender, EventArgs e)
        {
            this.rtbProgress.Visible = true;
            this.btnDetail.Visible = false;
        }

        private void gbtnOk_Click(object sender, EventArgs e)
        {
            if (myThread != null && myThread.IsAlive)
            {
                MessageBox.Show("内部错误，线程未停止");
                return;
            }

            this.Close();
        }

        #endregion

        #region Button

        private void btnOpenFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog myOpenFileDialog = new OpenFileDialog();
            myOpenFileDialog.ValidateNames = true;
            myOpenFileDialog.Multiselect = false;
            myOpenFileDialog.Filter = "纯真IP数据库QQWry.dat|*.dat";
            myOpenFileDialog.FilterIndex = 1;
            myOpenFileDialog.FileName = "QQWry.dat";
            myOpenFileDialog.AddExtension = true;
            if (myOpenFileDialog.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }
            this.tbPath.Text = myOpenFileDialog.FileName;
        }

        #endregion

        #region RadioButton

        private void rbtnMultiIP_CheckedChanged(object sender, EventArgs e)
        {
            this.nudIP.Enabled = this.rbtnMultiIP.Checked;
        }

        #endregion

        #endregion

        #region Thread

        private void ThreadSearch()
        {
            try
            {
                SearchLog(DirPath);
            }
            catch (ThreadAbortException)
            {
            }
        }

        private void ThreadAnaly()
        {
            try
            {
                string logs = ConfigurationManager.AppSettings["logs"];
                if (logs != "") LogPath = logs;
                if (!Directory.Exists(LogPath)) Directory.CreateDirectory(LogPath);

                outMsgInRichTextBox(string.Format("[{0}] 启动日志分析\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
                System.Diagnostics.Stopwatch Stepwatch = System.Diagnostics.Stopwatch.StartNew();
                System.Diagnostics.Stopwatch Totalwatch = System.Diagnostics.Stopwatch.StartNew();

                #region Initialization

                setMsg(0, "初始化配置……");

                string server = ConfigurationManager.AppSettings["server"];
                string database = ConfigurationManager.AppSettings["database"];
                string uid = ConfigurationManager.AppSettings["uid"];
                string pass = ConfigurationManager.AppSettings["pass"];
                string filtertype = this.rbtnInclude.Checked ? "" : " not ";
                List<string> filters = new List<string>(this.tbFilter.Text.Split(','));
                LogParserApi LogAnaly = null;

                DBO.DropTable();
                DBO.ClearTempRecord();

                outMsgInRichTextBox(string.Format("[{0}] 初始化配置完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                Stepwatch.Reset();
                Stepwatch.Start();

                #endregion

                int lineindex = 0;
                string sql = "";
                DataTable dt = null;
                foreach (string item in getListBox())
                {
                    outMsgInRichTextBox(string.Format("[{0}] 开始处理日志{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), item.ToString()));
                    
                    #region Analy

                    setMsg(lineindex * 9 + 1, string.Format("数据分析({0})", item.ToString()));

                    sql = string.Format(mySQL, item, filtertype, string.Join("';'", filters.ToArray()));
                    LogAnaly = new LogParserApi();
                    try
                    {
                        LogAnaly.InitSQLServer(server, database, uid, pass);
                        LogAnaly.Execute(sql);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                        return;
                    }

                    outMsgInRichTextBox(string.Format("[{0}] 数据分析完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                    Stepwatch.Reset();
                    Stepwatch.Start();

                    #endregion

                    #region Clear

                    setMsg(lineindex * 9 + 2, string.Format("数据清理({0})", item.ToString()));

                    try
                    {
                        DBO.ClearRecord();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                        return;
                    }

                    outMsgInRichTextBox(string.Format("[{0}] 数据清理完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                    Stepwatch.Reset();
                    Stepwatch.Start();

                    #endregion

                    #region UpdateDefaultSite

                    setMsg(lineindex * 9 + 3, string.Format("更新站点ID信息({0})", item.ToString()));
                                        
                    dt = DBO.getSiteName();
                    foreach(DataRow dr in dt.Rows)
                    {
                        if(item.Contains(dr["keywords"].ToString()))
                        {
                            DBO.UpdateSitename(dr["sitename"].ToString());
                        }
                    }
                    dt.Dispose();

                    outMsgInRichTextBox(string.Format("[{0}] 更新站点ID信息完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                    Stepwatch.Reset();
                    Stepwatch.Start();

                    #endregion

                    #region UpdateIPAddress

                    if (UpdateIPAddress)
                    {
                        setMsg(lineindex * 9 + 4, string.Format("填充IP地址信息({0})", item.ToString()));

                        dt = DBO.getIPList("Analy_temp", UpdateIPNumber);
                        QQWryHelper QQWry = new QQWryHelper(QQWryPath);
                        IPLocation loc = new IPLocation();
                        Int64 num = 0;
                        Int64 count = dt.Rows.Count;
                        foreach (DataRow dr in dt.Rows)
                        {
                            try
                            {
                                loc = QQWry.GetIPLocation(dr[0].ToString());
                                DBO.UpdateIPAddress("Analy_temp", loc);
                                num++;
                                setMsg(lineindex * 9 + 4, string.Format("填充IP地址信息……,已填充：{0}/{1}", num, count));
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show(ex.Message);
                                return;
                            }
                        }
                        dt.Dispose();

                        outMsgInRichTextBox(string.Format("[{0}] 填充IP地址信息完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                    }
                    Stepwatch.Reset();
                    Stepwatch.Start();

                    #endregion

                    #region UpdateServerType

                    setMsg(lineindex * 9 + 5, string.Format("填充服务器类型({0})", item.ToString()));

                    try
                    {
                        dt = DBO.getServerType();
                        foreach (DataRow dr in dt.Rows)
                        {
                            if (item.Contains(dr["keywords"].ToString()))
                            {
                                DBO.UpdateServerType(dr["stype"].ToString().ToLower() == "true" ? "1" : "0");
                            }
                        }
                        dt.Dispose();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                        return;
                    }

                    outMsgInRichTextBox(string.Format("[{0}] 填充服务器类型完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                    Stepwatch.Reset();
                    Stepwatch.Start();

                    #endregion

                    #region Import

                    setMsg(lineindex * 9 + 6, string.Format("分离按IP访问统计结果({0})", item.ToString()));

                    try
                    {
                        DBO.AddRecordbyIP();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                        return;
                    }

                    outMsgInRichTextBox(string.Format("[{0}] 分离按IP访问统计结果完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                    Stepwatch.Reset();
                    Stepwatch.Start();

                    setMsg(lineindex * 9 + 7, string.Format("分离按页面访问统计结果({0})", item.ToString()));

                    try
                    {
                        DBO.AddRecordbyPage();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                        return;
                    }

                    outMsgInRichTextBox(string.Format("[{0}] 分离按页面访问统计结果完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                    Stepwatch.Reset();
                    Stepwatch.Start();

                    setMsg(lineindex * 9 + 8, string.Format("IIS日志概要临时数据统计({0})", item.ToString()));

                    try
                    {
                        DBO.AddRecordGeneralTemp();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                        return;
                    }

                    outMsgInRichTextBox(string.Format("[{0}] IIS日志概要临时数据统计完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                    Stepwatch.Reset();
                    Stepwatch.Start();

                    #endregion

                    #region Clear

                    setMsg(lineindex * 9 + 9, string.Format("清理临时数据({0})", item.ToString()));

                    try
                    {
                        DBO.DropTable();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                        return;
                    }

                    outMsgInRichTextBox(string.Format("[{0}] 清理临时数据完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                    Stepwatch.Reset();
                    Stepwatch.Start();

                    #endregion

                    lineindex++;
                }

                #region General

                setMsg(lineindex * 9 + 1, "IIS日志概要统计");

                try
                {
                    DBO.AddRecordGeneral();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return;
                }

                outMsgInRichTextBox(string.Format("[{0}] 日志概要统计完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                Stepwatch.Reset();
                Stepwatch.Start();

                #endregion

                #region ClearRecord

                setMsg(lineindex * 9 + 2, "清理IIS日志概要临时数据");

                try
                {
                    DBO.ClearTempRecord();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return;
                }

                outMsgInRichTextBox(string.Format("[{0}] 清理IIS日志概要临时数据完成，耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Stepwatch.Elapsed));
                Stepwatch.Reset();
                Stepwatch.Start();

                #endregion

                setMsg(lineindex * 9 + 3, string.Format("日志分析完成，总计耗时：{0}", Totalwatch.Elapsed));
                outMsgInRichTextBox(string.Format("[{0}] 日志分析完成，总耗时：{1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), Totalwatch.Elapsed));
                Totalwatch.Stop();
                setButton(true);
                MessageBox.Show("日志分析完成");
            }
            catch (ThreadAbortException)
            {
            }
        }

        #endregion

        #region Method

        private void SearchLog(string Path)
        {
            string[] myFiles=System.IO.Directory.GetFiles(Path);
            foreach (string file in myFiles) AddItem(file);

            string[] myDirs=System.IO.Directory.GetDirectories(Path);
            foreach (string dir in myDirs) SearchLog(dir);

        }

        private List<string> getListBox()
        {
            if (this.InvokeRequired)
            {
                return this.Invoke(new myDeleGategetListBox(getListBox)) as List<string>;
            }
            else
            {
                List<string> items = new List<string>();
                for (int i = 0; i < this.lbFiles.Items.Count; i++)
                {
                    items.Add(this.lbFiles.Items[i].ToString());
                }
                return items;
            }
        }

        private void AddItem(string file)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGateAddItem(AddItem), new object[] { file });
            }
            else
            {
                this.lbFiles.Items.Add(file);
            }
        }

        private void setMsg(int index, string s)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGatesetMsg(setMsg), new object[] { index, s });
            }
            else
            {
                this.progressBar1.Value = index;
                this.lblMsg.Text = s;
            }
        }

        private void outMsgInRichTextBox(string s)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGateoutMsgInRichTextBox(outMsgInRichTextBox), new object[] { s });
            }
            else
            {
                try
                {
                    this.rtbProgress.AppendText(s);
                    FileStream fs = new FileStream(LogPath + @"\" + DateTime.Now.ToString("yyyy-MM-dd") + @".log", FileMode.Append, FileAccess.Write, FileShare.Read);
                    StreamWriter text = new StreamWriter(fs);
                    text.WriteLine(s);
                    text.Flush();
                    fs.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private void setButton(bool b)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGatesetButton(setButton), new object[] { b });
            }
            else
            {
                this.gbtnOk.Enabled = b;
            }
        }

        #endregion
    }
}
